package cn.jserv.ddns.service;

import cn.jserv.ddns.data.IpChangeEvent;
import cn.jserv.ddns.data.UploadVo;
import cn.jserv.ddns.util.HttpUtils;
import com.google.gson.Gson;
import com.huawei.hilink.event.Event;
import com.huawei.hilink.event.EventFilter;
import com.huawei.hilink.event.EventPublisher;
import com.huawei.hilink.event.EventSubscriber;
import com.huawei.hilink.openapi.plugin.PluginData;
import com.huawei.hilink.openapi.system.SystemInfo;
import com.huawei.hilink.openapi.system.WANInfo;
import com.huawei.hilink.util.CollectionUtil;
import com.huawei.hilink.util.Logger;
import com.huawei.hilink.util.LoggerFactory;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author 蒋登伟
 * @create 2022-03-15 15:58
 */
public class ResolutionService implements EventSubscriber {

    public void activate() {
        scheduledExecutorService = new ScheduledThreadPoolExecutor(10,
                new BasicThreadFactory.Builder().namingPattern("ddns-schedule-pool-%d").daemon(true).build());
        scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(ipChangeTask, 0, 120, TimeUnit.SECONDS);
    }

    public void deactivate() {
        scheduledFuture.cancel(true);
        scheduledExecutorService.shutdown();
    }

    @Override
    public Set<String> getSubscribedEventTypes() {
        return CollectionUtil.newUnmodifiableSet(IpChangeEvent.TYPE);
    }

    @Override
    public EventFilter getEventFilter() {
        return new EventFilter() {
            @Override
            public boolean apply(Event event) {
                return true;
            }
        };
    }

    @Override
    public void receive(Event event) {
        Map<String, String> config = pluginDataHandle.getDatas();
        String token = config.get("token");
        if (StringUtils.isEmpty(token)) {
            return;
        }
        String ipAddress = event.getPayload();
        UploadVo uploadVo = new UploadVo(token, ipAddress);
        try {
            Response response = HttpUtils.post("https://plugin.jserv.cn/ddns/upload", GSON.toJson(uploadVo));
            logger.info("更新IP地址结果:", Objects.requireNonNull(response.body()).string());
        } catch (IOException e) {
            logger.exception("更新IP地址错误:", e);
        }
    }

    protected void setPluginData(PluginData pluginData) {
        this.pluginDataHandle = pluginData;
    }

    protected void unsetPluginData(PluginData pluginData) {
        this.pluginDataHandle = null;
    }

    protected void setSystemInfo(SystemInfo systemInfo) {
        systemInfoHandle = systemInfo;
    }

    protected void unsetSystemInfo(SystemInfo systemInfo) {
        systemInfoHandle = null;
    }

    protected void setEventPublisher(EventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    protected void unsetEventPublisher(EventPublisher eventPublisher) {
        this.eventPublisher = null;
    }

    private final TimerTask ipChangeTask = new TimerTask() {
        @Override
        public void run() {
            WANInfo wanInfo = systemInfoHandle.getWANInfo();
            String newIpAddress = wanInfo.IPAddress;
            logger.debug("当前IP地址：" + newIpAddress);
            if (!newIpAddress.equals(ipAddress)) {
                ipAddress = newIpAddress;
                pluginDataHandle.setData("ipAddress", ipAddress);
                IpChangeEvent ipChangeEvent = new IpChangeEvent("hilink/ddns/ip/change", ipAddress);
                eventPublisher.post(ipChangeEvent);
            }
        }
    };

    private ScheduledExecutorService scheduledExecutorService;

    private PluginData pluginDataHandle;

    private SystemInfo systemInfoHandle;

    private EventPublisher eventPublisher;

    private String ipAddress;

    private ScheduledFuture<?> scheduledFuture;

    private static final Gson GSON = new Gson();

    private static final Logger logger = LoggerFactory.getLogger(RestfulService.class);

}
